import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import java.io.*;
import java.util.*;

/**
 * Main class SchnitzelMIDlet.
 */
public final class SchnitzelMIDlet extends MIDlet implements CommandListener, ItemCommandListener, ItemStateListener {
    private static final int DefaultTimeout = 2200;
    private static final Command CMD_EXIT = new Command("Exit", Command.EXIT, 1);    
    private final Command backwardButton, forwardButton, quitButton, okButton;// menuButton; 
    private Command confirmButton, playButton, hintButton;
    private Display display; 
    private String wrongAnswer, rightAnswer;
    private Form mainForm;
    private List advSelector;
    private ChoiceGroup choiceNode;
    private TextField textAnswer;
    private Adventure adv = null;
    private Alert splashScreenAlert;
    private Image splashScreen, imgRightAnswer, imgWrongAnswer;
    private boolean imageLoaded;
    private boolean firstTime;
    private Logger myLogger;
            
	// Constructor       
    public SchnitzelMIDlet() {
		myLogger = new Logger();
		myLogger.log("started");
        display = Display.getDisplay(this);
        forwardButton = new Command("Forward", Command.OK, 1);
    	okButton = new Command("Ok", Command.OK, 1);
    	playButton = new Command("Play", Command.OK, 1);
    	confirmButton = new Command("Confirm", Command.OK, 1);
    	hintButton = new Command("Hint", Command.BACK, 1);
    	backwardButton = new Command("Backward", Command.BACK, 1);
        quitButton =  new Command("Quit", Command.BACK, 1);
		//        rightAnswer = " Your answer is right!\n Your new score is: ";
        wrongAnswer = " Not quite right. Try again!";        
                        
    // Load Splash Screen
                            
        try {
		    InputStream is = this.getClass().getResourceAsStream("splashScreen.png");
		    splashScreen = Image.createImage(is);
		    is.close();        
            imageLoaded = true;
        } catch (java.io.IOException ex) {
        }
        if (imageLoaded)
            splashScreenAlert = new Alert("Schnitzelhunt", "", splashScreen, AlertType.INFO);
        else
            splashScreenAlert = new Alert("Schnitzelhunt", "    Welcome to Schnitzelhunt", splashScreen, AlertType.INFO);                
        splashScreenAlert.setTimeout(DefaultTimeout);

    // Load Image for right answer
        
        try {
		    InputStream is = this.getClass().getResourceAsStream("rightAnswer.png");
		    imgRightAnswer = Image.createImage(is);
		    is.close();        
        } catch (java.io.IOException ex) {
        }

    // Load Image for wrong answer

        try {
		    InputStream is = this.getClass().getResourceAsStream("wrongAnswer.png");
		    imgWrongAnswer = Image.createImage(is);
		    is.close();        
        } catch (java.io.IOException ex) {
        }

        firstTime = true;
    }
 
    
    protected void startApp() {
 
        if (firstTime) {

        // Load Adventure Selector 
            showAdventures();
            firstTime = false;
        }
    }
    
    protected void pauseApp() {
        // Place your code here.
    }
    
    protected void destroyApp(boolean unconditional) {
        // Place your code here.
    }    

    /**
	 * Displays a list of available adventures 
	 */

    public void showAdventures(){
            Image[] imageArray = null;

            try {
    		    InputStream is = this.getClass().getResourceAsStream("schnitzel_list.png");
    		    Image schnitzel = Image.createImage(is);
                is = this.getClass().getResourceAsStream("roland_list.png");
    		    Image roland = Image.createImage(is);
                is = this.getClass().getResourceAsStream("gw2_list.png");
    		    Image gw2 = Image.createImage(is);    		    
    		    is.close();        
                imageArray = new Image[] { gw2, roland, schnitzel };
            } catch (java.io.IOException ex) {
            }
                    
            String[] stringArray = { "The GW 2 Adventure", "The Bremen Adventure", "The Crazy Schnitzelhunt" };    
            advSelector = new List("Select an adventure", Choice.IMPLICIT, stringArray, imageArray);
            advSelector.addCommand(CMD_EXIT);
            advSelector.setCommandListener(this);
            display.setCurrent(splashScreenAlert, advSelector);    
    }

    /**
	 * Handles the actions that will be performed after changing a form 
	 */
    public void itemStateChanged(Item item){
    } 

	
    /**
     * Handles the actions that will be performed after pressing a command button 
     */
    public void commandAction(Command c, Displayable d) {
		
		// Adventure is selected
		
	    if (c == List.SELECT_COMMAND) {
            if (d.equals(advSelector)) {
                
                String advImage = "";
                imageLoaded = false;
                                
                switch (((List)d).getSelectedIndex()) {
                
                    case 0: // GW2 adventure

                    // Load Adventure File                                 
                      	try {
                      	    InputStream adventure_stream = this.getClass().getResourceAsStream("gw2_adventure.xml");
                      	    adv = AdventureLoader.load(adventure_stream);	    
                      	    adventure_stream.close();
                      	} catch(Exception e) {
                      	    mainForm.append(new StringItem(null, "Could not load adventure: " + e.getMessage()));
                      	}    

                        advImage = "gw2_splashScreen.png";

                        break;                
                                        
                    case 1: // Bremen Adventure

                    // Load Adventure File                                 
                      	try {
                      	    InputStream adventure_stream = this.getClass().getResourceAsStream("bremen_history.xml");
                      	    adv = AdventureLoader.load(adventure_stream);	    
                      	    adventure_stream.close();
                      	} catch(Exception e) {
                      	    mainForm.append(new StringItem(null, "Could not load adventure: " + e.getMessage()));
                      	}    

                        advImage = "roland_splashScreen.png";

                        break;
                        
                    case 2: // Dummy Adventure

                      	adv = AdventureLoader.load();	    
                        advImage = "schnitzel_splashScreen.png";                                        

                        break;
                }

            // Load Splash Screen 
                                    
                try {
        		    InputStream is = this.getClass().getResourceAsStream(advImage);
        		    splashScreen = Image.createImage(is);
        		    is.close();        
                    imageLoaded = true;
                } catch (java.io.IOException ex) {
                }
                if (imageLoaded)
                    splashScreenAlert = new Alert(adv.toString(), ""+adv.getDescription(), splashScreen, AlertType.INFO);
                else
                    splashScreenAlert = new Alert(adv.toString(), "    "+adv.toString(), splashScreen, AlertType.INFO);                
                splashScreenAlert.setTimeout(Alert.FOREVER); 
                splashScreenAlert.addCommand(quitButton);               
                splashScreenAlert.addCommand(playButton); 
                splashScreenAlert.setCommandListener(this);              
        
            // Create MainForm
                
                display.setCurrent(splashScreenAlert);
            }

        }else if (c == CMD_EXIT) {

    	// Exit button is clicked
    	
    	   destroyApp(false);
	       notifyDestroyed();
	
        }else if (c == quitButton){	
	       
    	// Quit button is clicked -> go back to Adventure-Selector
	       
            display.setCurrent(advSelector);
        
        }else if (c == confirmButton) {

    	// Handles the actions after pressing the Confirm button according to the Game Node Task Type        
    	
            switch (adv.getCurrentNode().getTaskType()){
	    
            	case GameNode.TEXT_ANSWER:
                    handleTextAnswer();       
        	        break;
            }
            
        }else if (c == playButton) {
        
        // Game is started 
        
    	    mainForm = createMainForm(adv.toString(), adv.getCurrentNode());
            display.setCurrent(mainForm);
        
        }else if (c == forwardButton) {
        
        // Forward after a description text 
			adv.chooseSelection(0);        
    	    mainForm = createMainForm(adv.toString(), adv.getCurrentNode());
            display.setCurrent(mainForm);
        }         	
        else if (c == hintButton) {
        
        // Show hint 
            mainForm = createMainForm(adv.toString(), adv.getCurrentNode());
            Alert hint = new Alert(adv.toString()+"          Score: " + adv.getScore(), adv.getCurrentNode().getHint(), imgRightAnswer, AlertType.INFO);                                        
            hint.addCommand(backwardButton);
            hint.setTimeout(Alert.FOREVER);
            adv.getCurrentNode().decreaseScore(2);
            display.setCurrent(hint);        
        } 

    }
    
    
    /**
     * Handles the actions that will be performed after pressing an item button or hyperlink
     */
    public void commandAction(Command c, Item item) {

        switch (adv.getCurrentNode().getTaskType()){
	    
        	case GameNode.TEXT_SELECTION:  	
                handleTextSelection(c, item);
                break;

        	case GameNode.IMAGE_SELECTION:
                handleImageSelection(c, item);       
        	    break;
        	    
        	case GameNode.DESCISION_POINT:
                handleDescisionPoint(c, item);       
        	    break;        	                                  	    
        }
    }    

	private Alert rightAnswerAlert() {
		return new Alert(adv.toString()+ "          Score: " + adv.getScore(), 
						 rightAnswerString(), 
						 imgRightAnswer, 
						 AlertType.CONFIRMATION); 
	}
	
	private String rightAnswerString() {
		String ret;
		if (adv.getCurrentNode().getLastNode().getMaxScore() > 0) {
			if (adv.getCurrentNode().getLastNode().getScore() > 0) {
				ret = "Your answer is right! You got " +
					adv.getCurrentNode().getLastNode().getScore() + 
					" out of " +
					adv.getCurrentNode().getLastNode().getMaxScore() + 
					" points!\n";
				ret += "Now you have a overall score of " +
					adv.getScore() +
					"!";
			} else {
				ret = "Your answer is right now, but you get NO POINTS for " +
					"this node! You could have reached " +
					adv.getCurrentNode().getLastNode().getMaxScore() + 
					". Try harder!";
			}
		} else {
			ret = "Let's go on to the next riddle!";
		}
		return ret;
	}


    /**
	 * Handle situation if GameNode is TEXT_ANSWER
	 */    
    public void handleTextAnswer(){
		
        boolean correctanswer = false;
        for(int i = 0; i<adv.getCurrentNode().getSolNo(); i++){
		    if (adv.getCurrentNode().getSolName(i).equals(textAnswer.getString())){
           		correctanswer = true;                        
                adv.chooseSelection(i);
		        mainForm = createMainForm(adv.toString(), adv.getCurrentNode());
                Alert result = rightAnswerAlert();
                display.setCurrent(result, mainForm);
		        break;
	        }
	        if (!correctanswer){
//				adv.chooseSelection(-1);
                Alert result = new Alert(adv.toString()+"          Score: " + adv.getScore(), wrongAnswer, imgWrongAnswer, AlertType.ERROR);                                        
                display.setCurrent(result, mainForm);                                       
            }
        }
        if (!correctanswer)
    		if (adv.getCurrentNode().getScore() != 0)
	       	    adv.getCurrentNode().decreaseScore(1);
    }


    /**
	 * Handle situation if GameNode is TEXT_SELECTION
	 */
    public void handleTextSelection(Command c, Item item){
        int selectedText = -1;
	    try {
            StringItem textAnswer = (StringItem) item;
            String label = textAnswer.getLabel().substring(0, (textAnswer.getLabel().length()-2));
            selectedText = Integer.parseInt (label) -1;
            if (selectedText != -1){
                GameNode targetNode = (adv.getCurrentNode()).getSolTargetNode(selectedText);
				adv.chooseSelection(selectedText);
                if (targetNode == null){
                    Alert result = new Alert(adv.toString()+"          Score: " + adv.getScore(), wrongAnswer, imgWrongAnswer, AlertType.ERROR);                    
                    textAnswer.removeCommand(c);
                    textAnswer.setFont(Font.getFont(Font.FACE_SYSTEM, Font.STYLE_ITALIC, Font.SIZE_MEDIUM));   
                    display.setCurrent(result, mainForm);                    
                }else{             
                    mainForm = createMainForm(adv.toString(), adv.getCurrentNode());
                    Alert result = rightAnswerAlert();
                    display.setCurrent(result, mainForm);
                }
            }
	    } catch (Exception e) {
			System.out.println("Error in handleTextSelection: " + e);
			//  was not a number
	    }                  
    }
    

    /**
	 * Handle situation if GameNode is IMAGE_SELECTION
	 */
    public void handleImageSelection(Command c, Item item){
		
        int selectedImage = -1;
	    try {
            ImageItem imgAnswer = (ImageItem) item;
            selectedImage = Integer.parseInt (imgAnswer.getAltText());
			System.out.println("Image chosen: " + selectedImage);
            if (selectedImage > -1){	    		    
				adv.chooseSelection(selectedImage);
                if ((adv.getLastNode()).getSolTargetNode(selectedImage) == null){
					System.out.println("Wrong answer image selected.");
                    Alert result = new Alert(adv.toString()+"          Score: " + adv.getScore(), wrongAnswer, imgWrongAnswer, AlertType.ERROR);                                        
       			    imgAnswer.removeCommand(c);
                    display.setCurrent(result, mainForm);        			
    		    } else {   		    
					System.out.println("Yeah, right image selected.");
                    mainForm = createMainForm(adv.toString(), adv.getCurrentNode());
                    display.setCurrent(rightAnswerAlert(), mainForm);
                }
            } else {
				System.out.println("No image selected.");
			}
	    } catch (Exception e){
			//es war keine Zahl
			System.out.println("Error in handleImageSelection: " + e);
	    }                       
    }
    
    /**
	 * Handle situation if GameNode is DESCISION_POINT
	 */
    public void handleDescisionPoint(Command c, Item item){
        int selectedText = -1;
	    try {
            StringItem textAnswer = (StringItem) item;
            String label = textAnswer.getLabel().substring(0, (textAnswer.getLabel().length()-2));
            selectedText = Integer.parseInt (label) -1;
            if (selectedText != -1){
                GameNode targetNode = (adv.getCurrentNode()).getSolTargetNode(selectedText);
				adv.chooseSelection(selectedText);
                if (targetNode == null){   
                    display.setCurrent(mainForm);                    
                }else{             
                    mainForm = createMainForm(adv.toString(), adv.getCurrentNode());
                    display.setCurrent(mainForm);
                }
            }
	    } catch (Exception e) {
			System.out.println("Error in handleDescisionPoint: " + e);
			//  was not a number
	    }                  
    }

    /** 
     * Create MainForm
     */
    public Form createMainForm(String title, GameNode gamenode){        
        Form newForm = null; 
        
        Vector commands = new Vector();                            
//        commands.addElement(forwardButton);
//        commands.addElement(backwardButton);        
        commands.addElement(quitButton);
		
    	title += "          Score: " + adv.getScore();            

        if (gamenode.getHint() != null)
            commands.addElement(hintButton);      

	// Create MainForm according to the Game Node Task Type    
    
        switch(gamenode.getTaskType()){
	    
        	case GameNode.TEXT_ANSWER:        
        	    commands.addElement(confirmButton);
        	    newForm = createTextAnswer(title, gamenode, commands);                 
        	    break;	    
        	    
        	case GameNode.TEXT_SELECTION:                
                commands.removeElement(quitButton);
        	    newForm = createTextSelection(title, gamenode, commands); 
        	    break;
                                
        	case GameNode.IMAGE_SELECTION:
                commands.removeElement(quitButton);
        	    newForm = createImageSelection(title, gamenode, commands);                 
        	    break;
                    
        	case GameNode.DESCRIPTION_TEXT:        
        	    commands.addElement(forwardButton);
        	    newForm = createDescriptionText(title, gamenode, commands);                 
        	    break;      

        	case GameNode.DESCISION_POINT:        
        	    newForm = createDescisionPoint(title, gamenode, commands);                 
        	    break;
        	    
        	case GameNode.END_POINT:        
        	    newForm = createEndPoint(title, gamenode, commands);                 
        	    break;                                       
        }        
	
	// if GameNode is End Note                	
	
    	if (gamenode.isEndNode()) {
	    
	    // Show Final Screen with Score
	    
    	    newForm.append(new StringItem(null, "Fine ! Your Score: " + adv.getScore()));
    	}
    	
        return newForm;
    }
        
    
    /*
     * Create MainForm if GameNode is TEXT_ANSWER
     */
    public Form createTextAnswer(String title, GameNode gamenode, Vector commands){        
        Form newForm = new Form(title);    
	
	// Create Commands
	
        for(int i = 0; i<commands.size(); i++){
	       newForm.addCommand((Command) commands.elementAt(i));
        }
        newForm.setCommandListener(this);            
	
	// Create Image if available
	
	    if (gamenode.getMedium() != null){
            Image img = null;
            try {
                InputStream is = this.getClass().getResourceAsStream(gamenode.getMedium());
                img = Image.createImage(is);
                is.close();
                ImageItem imgItem = new ImageItem(null, img, ImageItem.LAYOUT_CENTER, "");
                newForm.append(imgItem);            
            } catch(Exception e) {
                System.out.println("Error: " + e.getMessage());
            }            
        }	
	
	// Create Question
        StringItem question = new StringItem("Test your knowledge:\n", gamenode.toString()+"\n");	
        newForm.append(question); 
        
    // Create Textfield    
        textAnswer = new TextField("", "", 20, 0);
        newForm.append(textAnswer);       
        
        return newForm;
    }    
    
    
    /*
     * Create MainForm if GameNode is TEXT_SELECTION
     */
    public Form createTextSelection(String title, GameNode gamenode, Vector commands){        
        Form newForm = new Form(title);    
	
	// Create Commands
	
        for(int i = 0; i<commands.size(); i++){
	       newForm.addCommand((Command) commands.elementAt(i));
        }
        newForm.setCommandListener(this);            

	// Create Image if available
	
	    if (gamenode.getMedium() != null){
            Image img = null;
            try {
                InputStream is = this.getClass().getResourceAsStream(gamenode.getMedium());
                img = Image.createImage(is);
                is.close();
                ImageItem imgItem = new ImageItem(null, img, ImageItem.LAYOUT_CENTER, "");
                newForm.append(imgItem);            
            } catch(Exception e) {
                System.out.println("Error: " + e.getMessage());
            }            
        }
	
    // Create Question
    
        StringItem question = new StringItem("Test your knowledge:\n", gamenode.toString()+"\n");
        question.setLayout(StringItem.LAYOUT_LEFT);
//        question.setFont(Font.getFont(Font.FACE_SYSTEM, Font.STYLE_BOLD, Font.SIZE_MEDIUM));
        newForm.append(question);

    // Create list of possible answers

        for(int i = 0; i<gamenode.getSolNo(); i++){
    	    StringItem answer = new StringItem((i+1)+") ", gamenode.getSolName(i)+"\n", StringItem.HYPERLINK);
            answer.setDefaultCommand(new Command(" ", Command.ITEM, 1));
            answer.setItemCommandListener(this);
            newForm.append(answer);
        }        	
        return newForm;
    }
    
    
    /*
     * Create MainForm if GameNode is IMAGE_SELECTION
     */
    public Form createImageSelection(String title, GameNode gamenode, Vector commands){        
        Form newForm = new Form(title);    
	
	// Create Commands
	
        for(int i = 0; i<commands.size(); i++){
    	    newForm.addCommand((Command) commands.elementAt(i));
        }
        newForm.setCommandListener(this);            

    // Create Question
    
        StringItem question = new StringItem("Test your knowledge:\n", gamenode.toString()+"\n");
//        question.setFont(Font.getFont(Font.FACE_SYSTEM, Font.STYLE_BOLD, Font.SIZE_MEDIUM));
        newForm.append(question);	
	
	// Create Images
	        
        for(int i = 0; i<gamenode.getSolNo(); i++){
            Image img = null;
            try {
                InputStream is = this.getClass().getResourceAsStream(gamenode.getSourceFile(i));
                img = Image.createImage(is);
                is.close();
                //gamenode.getSolName(i);
                ImageItem imgItem = new ImageItem(null, img, ImageItem.LAYOUT_NEWLINE_AFTER, ""+i, ImageItem.HYPERLINK);
                imgItem.setDefaultCommand(new Command(" ", Command.ITEM, 1));
                imgItem.setItemCommandListener(this);
                newForm.append(imgItem);            
            } catch(Exception e) {
                System.out.println("Error: " + e.getMessage());
            }
        }       
        return newForm;
    }

    /*
     * Create MainForm if GameNode is DESCRIPTION_TEXT
     */
    public Form createDescriptionText(String title, GameNode gamenode, Vector commands){        
        Form newForm = new Form(title);    
	
	// Create Commands
	
        for(int i = 0; i<commands.size(); i++){
	       newForm.addCommand((Command) commands.elementAt(i));
        }
        newForm.setCommandListener(this);            
	
	// Create Image if available
	
	    if (gamenode.getMedium() != null){
            Image img = null;
            try {
                InputStream is = this.getClass().getResourceAsStream(gamenode.getMedium());
                img = Image.createImage(is);
                is.close();
                ImageItem imgItem = new ImageItem(null, img, ImageItem.LAYOUT_CENTER, "");
                newForm.append(imgItem);            
            } catch(Exception e) {
                System.out.println("Error: " + e.getMessage());
            }            
        }	
	
	// Create Description
        newForm.append(new StringItem("Learn it:\n", gamenode.toString()));	     
        
        return newForm;
    } 

    /*
     * Create MainForm if GameNode is DESCISION_POINT
     */
    public Form createDescisionPoint(String title, GameNode gamenode, Vector commands){        
        Form newForm = new Form(title);    
	
	// Create Commands
	
        for(int i = 0; i<commands.size(); i++){
	       newForm.addCommand((Command) commands.elementAt(i));
        }
        newForm.setCommandListener(this);            
	
	// Create Image if available
	
	    if (gamenode.getMedium() != null){
            Image img = null;
            try {
                InputStream is = this.getClass().getResourceAsStream(gamenode.getMedium());
                img = Image.createImage(is);
                is.close();
                ImageItem imgItem = new ImageItem(null, img, ImageItem.LAYOUT_CENTER, "");
                newForm.append(imgItem);            
            } catch(Exception e) {
                System.out.println("Error: " + e.getMessage());
            }            
        }	
	
	// Create Description
        newForm.append(new StringItem("Choose your way:\n", gamenode.toString()));	     
    
    // Create descisions

        for(int i = 0; i<gamenode.getSolNo(); i++){
    	    StringItem answer = new StringItem((i+1)+") ", gamenode.getSolName(i)+"\n", StringItem.HYPERLINK);
            answer.setDefaultCommand(new Command(" ", Command.ITEM, 1));
            answer.setItemCommandListener(this);
            newForm.append(answer);
        }    
        
        return newForm;
    }

    /*
     * Create MainForm if GameNode is END_POINT
     */
    public Form createEndPoint(String title, GameNode gamenode, Vector commands){        
        Form newForm = new Form(title);    
	
	// Create Commands
	
        for(int i = 0; i<commands.size(); i++){
	       newForm.addCommand((Command) commands.elementAt(i));
        }
        newForm.setCommandListener(this);            
	
	// Create Image if available
	
	    if (gamenode.getMedium() != null){
            Image img = null;
            try {
                InputStream is = this.getClass().getResourceAsStream(gamenode.getMedium());
                img = Image.createImage(is);
                is.close();
                ImageItem imgItem = new ImageItem(null, img, ImageItem.LAYOUT_CENTER, "");
                newForm.append(imgItem);            
            } catch(Exception e) {
                System.out.println("Error: " + e.getMessage());
            }            
        }	
	
	// Create Description
        newForm.append(new StringItem("Congratulations:\n", gamenode.toString()));	     
        
        return newForm;
    }

}

/*
  Hinweise zum Menu
  
Links:
  immer Menu
Rechts entweder:
  Nichts, Hint, Next, Ok
MainMenu:
  Resume Game
  New Game
  Highscores
  Settings
  Instructions
wenn MainMenu offen:
  unten Exit
Spielmenu:
  Forward
  Backward
wenn Spielmenu offen:
  unten Back und Go
*/

/*
    Code zum Aendern des Textstils
    
    StringItem wrong = new StringItem(null, wrongAnswer);        
    wrong.setFont(Font.getFont(Font.FACE_SYSTEM, Font.STYLE_BOLD | Font.STYLE_ITALIC, Font.SIZE_MEDIUM));
*/

/*	
	// Create ChoiceGroup

        
        String[] solutionNames = new String[gamenode.getSolNo()]; 
        for(int i = 0; i<gamenode.getSolNo(); i++){
            solutionNames[i] = gamenode.getSolName(i);    
        }
    
        choiceNode = new ChoiceGroup(gamenode.toString(), Choice.EXCLUSIVE, solutionNames, null);       
        newForm.append(choiceNode);       
*/